# -*- coding:utf-8 -*-
import re,os,datetime,time

class Object(object):
    pass

class Myjson(object):
    def __init__(self,content=''):
        self.content=content
        self.coding_list=['utf-8', 'gbk', 'gb2312', 'gb18030']
        self.data={}
    def decode_str(self,data,coding=''):
        if type(data)==type(u''):
            return data
        if coding!='':
            return data.decode(coding,'ignore')
        else:
            for coding in self.coding_list:
                try:
                    rdata=data.decode(coding)
                    return rdata
                except:
                    pass
            return data.decode('utf-8','ignore')

    def encode_attr(self,value):
        if isinstance(value,bool):
            return str(value).lower()
        elif isinstance(value,(int,float,long)):
            return str(value)
        elif isinstance(value,(str,unicode)):                    #str
            return '"%s"'%value
        elif value==None:                               #None
            return 'null'
        elif isinstance(value,list):                    #list
            list_str=''
            for i in value:
                list_str=list_str+self.encode_attr(i)+','
            return '[%s]'%list_str[:-1]
        elif isinstance(value,dict):                     #dict
            json_str=''
            for k,v in value.items():
                js_str=self.encode_attr(v)
                json_str+='"%s":%s,'%(k,js_str)
            return "{%s}"%json_str[:-1]
        else:
            print 'XXXX',value
        
    def dumps(self,obj={}):
        if obj:
            json_str=self.encode_attr(obj)
        else:
            json_str=self.encode_attr(self.data)
        return json_str
    ##############################################################

    def cnext(self):
        return self.content[self.i]
    def get_next(self):
        if self.i<len(self.content):
            c=self.cnext()
            self.i+=1
            return c
        return None
    def get_unicode(self):
        v_value=''
        hexc=''
        while True:
            tcc=self.get_next()
            if tcc.lower()  in self.hex_sign:
                hexc+=tcc
                if len(hexc)>=4:
                    v_value+=unichr(eval('0x'+hexc))
                    break
            else:
                v_value+='\\'
                v_value+='u'
                v_value+=hexc
                v_value+=tcc
                break
        return v_value
    def get_name(self):                             #get name
        v_value=''
        c=self.get_next()
        while c!='"' and c!=None:
            c=self.get_next()
            pass
        while True:
            c=self.get_next()
            if c=='"':
                break
            elif c=='\\':
                tc=self.get_next()
                if tc=='u':                         #unicode
                    v_value+=self.get_unicode()
                else:
                    v_value+=c
                    v_value+=tc
            else:
                v_value+=c
                
        #print v_name
        return v_value

    def get_str(self):                              #get value
        v_value=''
        while True:
            c=self.get_next()
            if c=='"':
                break
            elif c=='\\':
                tc=self.get_next()
                if tc=='u':                         #unicode
                    '''
                    hexc=''
                    while True:
                        tcc=self.get_next()
                        if tcc.lower()  in self.hex_sign:
                            hexc+=tcc
                            if len(hexc)>=4:
                                v_value+=unichr(eval('0x'+hexc))
                                break
                        else:
                            v_value+=c
                            v_value+=tc
                            v_value+=hexc
                            break
                    '''
                    v_value+=self.get_unicode()
                else:
                    v_value+=c
                    v_value+=tc
            else:
                v_value+=c
        return v_value
    
    def get_none(self,c):                              #get value
        v_value=c
        while True:
            c=self.get_next()
            if c in self.end_sign:
                self.i-=1
                break
            else:
                v_value+=c
        if v_value.strip()=='null':
            return None
        else:
            raise Exception('None type error in positon: %d'%self.i)
    
    def get_bool(self,c):
        cc=c
        while True:
            tc=self.get_next()
            if tc in self.end_sign:
                self.i-=1
                break
            else:
                cc+=tc
        if cc.strip()=='true':
            return True
        elif cc.strip()=='false':
            return False
        else:
            print cc
            raise Exception('bool type error in position: %d'%self.i)
    def get_num(self,c):
        s_num=c
        while True:
            cc=self.get_next()
            if cc in self.end_sign:
                self.i-=1
                break
            else:
                s_num+=cc
        return eval(s_num.strip())
    def get_value(self):
        c=self.strip_space()
        if c=='"':
            v_value=self.get_str()
        elif c in 'tf':
            v_value=self.get_bool(c)
        elif c in '-1234567890e':
            v_value=self.get_num(c)
        elif c=='n':
            v_value=self.get_none(c)
        elif c=='[':
            v_value=self.get_list()
        elif c=='{':
            v_value=self.get_object()
        return v_value
    
    def get_list(self):
        r_list=[]
        c=self.strip_space()
        if c==']':
            return []
        else:
            self.i-=1
        while True:
            v_value=self.get_value()
            r_list.append(v_value)
            c=self.strip_space()
            if c==',':
                cc=self.strip_space()
                if cc==']':
                    return r_list
                else:
                    self.i-=1
                    continue
            elif c==']':
                return r_list
            else:
                raise Exception('list type error in position: %d'%self.i)
    
    def strip_space(self):
        while True:
            c=self.get_next()
            if c not in ' \t\n\r\v\f':
                return c

    def get_object(self):
        obj=Object()
        dict1={}
        c=self.strip_space()
        if c=='}':
            return {}
        else:
            self.i-=1
        while True:
            v_name=self.get_name()               #获得名称
            while self.get_next()!=':':          #过滤冒号
                pass
            v_value=self.get_value()
            dict1[v_name]=v_value
            c=self.strip_space()
            if c==',':
                cc=self.strip_space()
                if cc=='}':
                    break
                else:
                    self.i-=1
                    continue
            elif c=='}' or c==None:
                break
            else:
                raise Exception(c)
        return dict1

    def loads(self,json_str):
        self.content=self.decode_str(json_str.strip(),'utf-8')
        self.i=0
        self.end_sign='",]}:'                            #end sign
        self.hex_sign='1234567890abcdef'
        c=self.strip_space()
        if True or c=='{' :
            try:
                obj=self.get_object()
                return obj
            except Exception,e:
                print str(e)
                print self.i,self.content[self.i-20:self.i],'###',self.content[self.i:self.i+20]
                print 'error happen in position %d'%self.i
        else:
            print 'error'
            raise Exception('error json string')

    def __getitem__(self,key):
        return self.data[key]
    def __setitem__(self,key,value):
        self.data[key]=value
        
    def get_attr(self,obj,attr_str):
        obj.get(attr_str,None)
        
    def set_attr(self,obj,v_name,v_value):
        obj[v_name]=v_value
        return obj
    def del_attr(self,obj,v_name):
        obj.pop(v_name,'')
        return obj
    
def get_file_path(root_dir):
    file_list=os.walk(root_dir)
    for root,dirs,files in file_list:
        for f in files:
            path=os.path.join(root,f)
            yield path
    
def count_files(root_dir):
    count=0
    file_path_list=get_file_path(root_dir)
    mj=Myjson()
    for path in file_path_list:
        f=open(path)
        json_str=f.read()
        f.close()
        
        print path
        dict1=mj.loads(json_str)
        count+=1         
    return count

root_dir=r'D:\tmp\tjson'
#count=count_files(root_dir)

def print_json_dict(obj,i=0):
    if type(obj)==type([]):
        print '    '*i,'['
        for v in obj:
            print_json_dict(v,i+1)
        print '    '*i,']'
    elif type(obj)==type({}):
        print '    '*i,'{'
        for k,v in obj.items():
            print '    '*i,' ',str(k).encode('utf-8'),':'
            print_json_dict(v,i+1)
        print '    '*i,'}'
    else:
        print '    '*i,str(obj).encode('utf-8'),','

#print_json_dict(dict1)

def test():
    
    start=datetime.datetime.now()
    js_list=[]
    dict1={}
    for i in range(10000):
        jsobj={}
        jsobj["User"]={}
        jsobj["User"]["UserID"] = 10000
        jsobj["User"]["Age"] = 100
        jsobj["User"]["Name"]={}
        jsobj["User"]["Name"]["FirstName"] = "Han"
        jsobj["User"]["Name"]["LastName"] = "MM"
        jsobj["ishost"] = True
        jsobj["Time"] = "2012-9-19 21:14:30"
        jsobj["ID"] = 10086
        jsobj["Description"] = "对于JSON(JavaScript Object Notation)大家应该不陌生，它是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成"
        jsobj["StrArray"]=[]
        jsobj["StrArray"].append("hello")
        jsobj["StrArray"].append("json")
        jsobj["StrArray"].append("!")
        jsobj["IntArray"]=[]
        jsobj["IntArray"].append(1)
        jsobj["IntArray"].append(2)
        jsobj["IntArray"].append(3)
        jsobj["Price"] = 500.5
        jsobj["Title"] = "JavaScript Object Notation"

        jsobj["objArray"]=[]
        objarray={}
        objarray["Prov"] = "广东"
        objarray["City"] = "广州"
        jsobj["objArray"].append(objarray)
        
        objarray2={}
        objarray2["Prov"] = "湖南"
        objarray2["City"] = "长沙"
        jsobj["objArray"].append(objarray2)
        #js_list.append(jsobj)
        dict1[i]=jsobj
        #del jsobj
    #dict1={"a":js_list}
    jsobj=Myjson()
    json_str=jsobj.dumps(dict1)
    end=datetime.datetime.now()
    print 'encode: ',end-start
    #print json_str
    
    save_file=os.path.abspath('.').replace('\\','/')+'/json.txt'
    f=open(save_file,'w')
    f.write(json_str)
    f.close()
    print '#################'
    print len(json_str)
    
    f=open(save_file,'r')
    json_str=f.read()
    f.close()
    
    start=datetime.datetime.now()
    jsobj=Myjson()
    jsobj.loads(json_str)
    end=datetime.datetime.now()
    print 'decode: ',end-start
    
if __name__=='__main__':
    test()
##    f=open('d:/tmp/jsonpctest.txt','r')
##    data=f.read()
##    f.close()
##    mj=Myjson()
##    mj.loads(data)#["a"][0]["objArray"]
##    print 'end'




